#include "adc_temp.h"
#include "SysTick.h"

ADC_HandleTypeDef ADC1_Handler;					// ADC句柄

/***************************
* 函数名： ADC_Temp_Init
* 功能：ADC初始化函数
* 输入：无
* 输出：无
*/
void ADC_Temp_Init(void)
{
	RCC_PeriphCLKInitTypeDef ADC_CLKInit;
	
	ADC_CLKInit.PeriphClockSelection=RCC_PERIPHCLK_ADC;									// ADC外设时钟
	ADC_CLKInit.AdcClockSelection=RCC_ADCPCLK2_DIV6;										// 分频因子6时钟为72M/6=12MHz
	HAL_RCCEx_PeriphCLKConfig(&ADC_CLKInit);														// 设置ADC时钟
	
	ADC1_Handler.Instance=ADC1;
	ADC1_Handler.Init.DataAlign=ADC_DATAALIGN_RIGHT;										// 右对齐
	ADC1_Handler.Init.ScanConvMode=DISABLE;															// 非扫描模式
	ADC1_Handler.Init.ContinuousConvMode=DISABLE;												// 关闭连续转换
	ADC1_Handler.Init.NbrOfConversion=1;																// 1个转换在规则序列中，只转换序列1
	ADC1_Handler.Init.DiscontinuousConvMode=DISABLE;										// 禁止不连续采样模式
	ADC1_Handler.Init.NbrOfDiscConversion=0;														// 不连续采样通道数为0
	ADC1_Handler.Init.ExternalTrigConv=ADC_SOFTWARE_START;							// 软件触发
	HAL_ADC_Init(&ADC1_Handler);
	
	HAL_ADCEx_Calibration_Start(&ADC1_Handler);													// 校准ADC
	
}

/********************************************
* ADC底层驱动，引脚配置，时钟使能
* 该函数被HAL_ADC_Init()调用
* hadc：ADC句柄
********************************************/
void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	__HAL_RCC_ADC1_CLK_ENABLE();								// 使能ADC1时钟
	__HAL_RCC_GPIOA_CLK_ENABLE();								// 使能GPIOA时钟
	
	GPIO_InitStructure.Pin=GPIO_PIN_1;					// PA1
	GPIO_InitStructure.Mode=GPIO_MODE_ANALOG;		// 模拟
	GPIO_InitStructure.Pull=GPIO_NOPULL;				// 不带上下拉
	HAL_GPIO_Init(GPIOA,&GPIO_InitStructure);
}

/********************************************************
* 获得ADC值
* ch：通道值0~16，取值范围：ADC_CHANNEL_0~ADC_CHANNEL_16
* 返回：转换结果
********************************************************/
u16 Get_Adc(u32 ch)
{
	ADC_ChannelConfTypeDef ADC1_ChanConf;
	ADC1_ChanConf.Channel=ch;																// 通道
	ADC1_ChanConf.Rank=1;																		// 1个序列
	ADC1_ChanConf.SamplingTime=ADC_SAMPLETIME_239CYCLES_5;	// 采样时间
	HAL_ADC_ConfigChannel(&ADC1_Handler,&ADC1_ChanConf);		// 通道配置
	
	HAL_ADC_Start(&ADC1_Handler);														// 开启ADC
	HAL_ADC_PollForConversion(&ADC1_Handler,10);						// 轮询转换
	
	return (u16)HAL_ADC_GetValue(&ADC1_Handler);						// 返回最近一次ADC1规则组转换结果
}

/*****************************************
* 获取指定通道转换值，取times次平均
* times：获取次数
* 返回：通道ch的times次转换结果平均值
*****************************************/
u16 Get_ADC_Value(u32 ch,u8 times)
{
	u32 temp_val=0;
	u8 t;
	for(t=0;t<times;t++)
	{
		temp_val += Get_Adc(ch);
		delay_ms(5);
	}
	return temp_val/times;
}

/*******************************************************************************
* 获取温度值
* 公式：T(℃)={(Vsense - V25) / Avg_Slope}+25
*		其中，V25=Vsense在25度时数值（典型值为：1.43V）
*				Avg_Slope=温度与Vsense曲线平均斜率（单位为mv/℃或uv/℃）典型值为4.3mV/℃
* 返回：温度值（扩大100倍，单位：℃）
*******************************************************************************/
int Get_Temperature(void)
{
	u32 adcx;
	int result;
	double temperature;
	
	adcx = Get_ADC_Value(ADC_CHANNEL_TEMPSENSOR,10); 	// 读取内部温度传感器通道，10次取平均
	temperature=(float)adcx*(3.3/4096);								// 电压值
	temperature=(1.43-temperature)/0.0043+25;					// 转换为温度值
	result=temperature*=100;													// 扩大100倍
	
	return result;
}